using System;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;


namespace DictUtils
{

    public class Tokenizer
    {
        //public char[] delimiters = { '.', '!', '?' };
        string delimiters = ".?!";
        string start_delimiters = ".?! \t\n\r";
        private BinaryReader sr;
        private string buf = "";
        
        public Tokenizer(string s)
        {
            Stream stream = new FileStream(s,FileMode.Open);
            sr = new BinaryReader(stream);
        }

        public string GetLexem()
        {
            char c='\0';
            if (sr.BaseStream.Position < sr.BaseStream.Length)
            {

                bool ok;
                do
                {
                    ok = true;
                    try
                    {
                        c = sr.ReadChar();
                        while ((buf == "") && (start_delimiters.Contains(c.ToString())))   //!!!!!!!
                            c = sr.ReadChar();
                    }
                    catch (Exception ee)
                    {
                        //do nothing
                    }
                } while (!ok);

                try
                {
                    do
                    {
                        buf += c.ToString();
                        c = sr.ReadChar();
                        if (delimiters.Contains(c.ToString())) buf += c.ToString();
                    }
                    while ((!delimiters.Contains(c.ToString())) && (sr.BaseStream.Position < sr.BaseStream.Length));
                }
                catch (Exception ee)
                {
                    //do nothing
                }

                
                string tmp2 = buf;
                buf = "";
                
                return tmp2;
            }
            else
            {
                sr.Close();
                return null;
            }
        }



    }



    public class WordChecker
    {
        private ArrayList dic = new ArrayList();
        public WordChecker(string file_name)
        {
            TextReader rdr = new StreamReader(file_name);
            string s;
            while ((s = rdr.ReadLine()) != null)
            {
                dic.Add(s);
            }
        }
        public bool chek(string s)
        {
            
            //checking if -ness          
            if (!s.Contains("ness"))
                return false;
            // checking if not in a dictionaty
          //  if (dic.Contains(s))
            //    return false;

            return true;
        }
    }


    public class SyntaxParser: IDisposable
    {
        private WordChecker checker = new WordChecker("dict.txt");
        private TextWriter w;
        private bool disposed = false;

        public SyntaxParser()
        {
            w = new StreamWriter("output.txt");
        }
        public void parse(string filename)
        {
            string lex;
            Tokenizer my_tokenizer = new Tokenizer(filename);

            w.WriteLine("\n processing " + filename);
            w.WriteLine("--------------------------------");
            w.WriteLine();

            while ((lex = my_tokenizer.GetLexem()) != null)
            {
                if (checker.chek(lex))
                {
                    w.WriteLine("  {0}", lex);
                    w.WriteLine();
                }
            }    
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
//                    component.Dispose();
              //      w.Close();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here.
                // If disposing is false, 
                // only the following code is executed.
                //CloseHandle(handle);
                //handle = IntPtr.Zero;
                w.Close();
            }
            disposed = true;
        }

    
    }



    public class WordCounter
    {
        public WordCounter() { /* No interesting construction */ }
        //public char[] delimiters = {' ','.',',','!','?',':','-',';','\''};
        public char[] delimiters = { '.', '!', '?' };
        // Each object of this class keeps a running total of the files its processed
        // The following members hold this running information
        Int64 totalLines = 0;

        Int64 totalWords = 0;

        Int64 totalChars = 0;

        Int64 totalBytes = 0;
        private WordChecker checker = new WordChecker("dict.txt");
        // The set of all words seen (sorted alphabetically)
        SortedList wordCounter = new SortedList();

        // The following methods return the running-total info
        public Int64 TotalLines { get { return totalLines; } }

        public Int64 TotalWords { get { return totalWords; } }

        public Int64 TotalChars { get { return totalChars; } }

        public Int64 TotalBytes { get { return totalBytes; } }

        // This method calculates the statistics for a single file.
        // This file's info is returned via the out parameters
        // The running total of all files is maintained in the data members
        public Boolean CountStats(String pathname, Encoding fileEncoding, out Int64 numLines, out Int64 numWords, out Int64 numChars, out Int64 numBytes)
        {
            Boolean Ok = true;  // Assume success

            numLines = numWords = numChars = numBytes = 0;  // Initialize out params to zero
            try
            {
                // Attempt to open the input file for read-only access
                FileStream fsIn = new FileStream(pathname, FileMode.Open, FileAccess.Read, FileShare.Read);


                numBytes = fsIn.Length;
                using (StreamReader sr = new StreamReader(fsIn, fileEncoding, true))
                {
                    // Process every line in the file
                    for (String Line = sr.ReadLine(); Line != null; Line = sr.ReadLine())
                    {
                        numLines++;
                        numChars += Line.Length;

                        String[] Words = Line.Split(delimiters);  // Split the line into words

                        for (int Word = 0; Word < Words.Length; Word++)
                        {
                            if (Words[Word].Length > 0)
                            {	// Don't count empty strings
                                numWords++;
                                Words[Word] = Words[Word].ToLower();
                                if (!wordCounter.ContainsKey(Words[Word]))
                                {
                                    // If we've never seen this word before, add it to the sorted list with a count of 1
                                    //additional chech
                                    
                                    if (Words[Word].Length > 3)
                                        if (checker.chek(Words[Word]))
                                    wordCounter.Add(Words[Word], 1);
                                }
                                else
                                {
                                    // If we have seen this word before, just increment its count
                                    wordCounter[Words[Word]] = (Int32)wordCounter[Words[Word]] + 1;
                                }
                            }
                        }
                    }
                }
                // Explicitly close the StreamReader to properly flush all buffers
            }
            catch (FileNotFoundException)
            {
                // The specified input file could not be opened
                Ok = false;
            }

            // Increment the running totals with whatever was discovered about this file
            totalLines += numLines;
            totalWords += numWords;
            totalChars += numChars;
            totalBytes += numBytes;
            return (Ok);
        }

        // Returns an enumerator for the words (sorted alphabetically)
        public IDictionaryEnumerator GetWordsAlphabeticallyEnumerator()
        {
            return (IDictionaryEnumerator)wordCounter.GetEnumerator();
        }

        // Returns an enumerator for the words (sorted by occurrence)
        public IDictionaryEnumerator GetWordsByOccurrenceEnumerator()
        {
            // To create a list of words sorted by occurrence, we need another SortedList object
            SortedList sl = new SortedList();

            // Now, we'll iterate through the words alphabetically
            IDictionaryEnumerator de = GetWordsAlphabeticallyEnumerator();

            while (de.MoveNext())
            {
                // For each word, we create a new WordOccurrence object which
                // contains the word and its occurrence value.
                // The WordOccurrence class contains a CompareTo method which knows
                // to sort WordOccurrence objects by occurrence value and then alphabetically by the word itself.
                sl.Add(new WordOccurrence((int)de.Value, (string)de.Key), null);
            }

            // Return an enumerator for the words (sorted by occurrence)
            return (IDictionaryEnumerator)sl.GetEnumerator();
        }

        // Returns the number of unique words processed
        public int UniqueWords
        {
            get { return wordCounter.Count; }
        }
    }

    // This class is only used to sort the words by occurrence
    // An instance of this class is created for each word
    public class WordOccurrence : IComparable
    {
        // Members indicating the number of times this word occurred and the word itself
        private int occurrences;

        private String word;

        // Constructor
        public WordOccurrence(int occurrences, String word)
        {
            this.occurrences = occurrences;
            this.word = word;
        }

        // Sorts two WordOccurrence objects by occurrence first, then by word
        public int CompareTo(Object o)
        {
            // Compare the occurance of the two objects
            int n = occurrences - ((WordOccurrence)o).occurrences;

            if (n == 0)
            {
                // Both objects have the same ccurrance, sort alphabetically by word
                n = String.Compare(word, ((WordOccurrence)o).word, false, Thread.CurrentThread.CurrentCulture);
            }

            return (n);
        }

        // Return the occurrence value of this word
        public int Occurrences { get { return occurrences; } }

        // Return this word
        public String Word { get { return word; } }

        public override bool Equals(Object obj)
        {
            if (!(obj is WordOccurrence))
                return false;

            return (this.CompareTo(obj) == 0);
        }

        // Omitting getHashCode violates FxCop rule: EqualsOverridesRequireGetHashCodeOverride.
        public override int GetHashCode()
        {
            return occurrences + word.GetHashCode();
        }

        public static bool operator ==(WordOccurrence wo1, WordOccurrence wo2)
        {
            return wo1.Equals(wo2);
        }

        public static bool operator !=(WordOccurrence wo1, WordOccurrence wo2)
        {
            return !(wo1 == wo2);
        }

        public static bool operator <(WordOccurrence wo1, WordOccurrence wo2)
        {
            return (wo1.CompareTo(wo2) < 0);
        }

        public static bool operator >(WordOccurrence wo1, WordOccurrence wo2)
        {
            return (wo1.CompareTo(wo2) > 0);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////

}